#include "threadpool.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>

// 1.无返回值、无参数
void *test1(void *arg) {
    assert(arg == NULL);

    printf("test1: tid = %lu\n", pthread_self());
    sleep(1);

    return NULL;
}

// 2.有返回值、无参数
typedef struct Results2 {
    int result1;
    int result2;
} Results2;

void *test2(void *arg) {
    assert(arg == NULL);

    Results2 *results = (Results2 *)malloc(sizeof(Results2));
    if(results == NULL) {
        perror(" - ERROR: result1 allocation failed");
        exit(EXIT_FAILURE);
    }
    results->result1 = 100;
    results->result2 = 200;
    printf("test2: tid = %lu, result = %d, %d\n", 
        pthread_self(), results->result1, results->result2);
    sleep(2);

    return (void *)results;
}

//! C语言函数只能返回一个变量（函数返回值存储在寄存器%eax中）
// 3.有返回值、有参数
typedef struct Results3 {
    float result1;
} Results3;

typedef struct Args3 {
    int arg1;
    float arg2;
} Args3;

void *test3(void *arg) {
    assert(arg != NULL);

    Args3 *args = (Args3 *)arg;
    Results3 *results = (Results3 *)malloc(sizeof(Results3));
    if(results == NULL) {
        perror(" - ERROR: result3 allocation failed");
        exit(EXIT_FAILURE);
    }
    results->result1 = args->arg1 + args->arg2;
    printf("test3: tid = %lu, result = %f, args = %d, %f\n", 
        pthread_self(), results->result1, args->arg1, args->arg2);
    sleep(3);


    return (void *)results;
}

int main(int argc, char *argv[]) {
    ThreadPool *pool = threadpool_create(4, 10);

    Task task1 = {NULL, test1, NULL, false};
    pthread_mutex_init(&task1.mutex, NULL);
    threadpool_push(pool, &task1);

    Task task2 = {NULL, test2, NULL, false};
    pthread_mutex_init(&task2.mutex, NULL);
    threadpool_push(pool, &task2);

    Args3 args3 = {100, 200.0F};
    Task task3 = {NULL, test3, (void *)&args3, false};
    pthread_mutex_init(&task3.mutex, NULL);
    threadpool_push(pool, &task3);

    Task *tasks[] = {&task1, &task2, &task3};
    uint32_t tasks_count = sizeof(tasks) / sizeof(tasks[0]);
    uint32_t remaining_count = tasks_count;
    bool tasks_completed[] = {false, false, false};
    
    while(remaining_count){
        for(uint32_t i = 0; i < tasks_count; i++) {
            if(tasks_completed[i]) continue;

            pthread_mutex_lock(&tasks[i]->mutex);
            bool ready = tasks[i]->ready;
            pthread_mutex_unlock(&tasks[i]->mutex);

            if(!ready) continue;

            void *ret = tasks[i]->ret;    //! 不需要解锁，因为工作线程已完成任务，无共享资源
            // 任务有返回值
            if(ret != NULL) {
                // 按任务返回值类型强制转换解析
                if(i == 1) {
                    Results2 *results2 = (Results2 *)ret;
                    printf("tesst2 result: %d, %d\n", results2->result1, results2->result2);
                }
                else if(i == 2) {
                    Results3 *results3 = (Results3 *)ret;
                    printf("task3 result: %f\n", results3->result1);
                }
            }
            tasks_completed[i] = true;
            remaining_count--;
        }
        usleep(50000);
    }

    // 释放堆内存
    for(uint32_t i = 0; i < tasks_count; i++) {
        Task *task = tasks[i];
        free(task->ret);
        task->ret = NULL;
        task->ready = false;
    }

    // 销毁互斥锁
    for(uint32_t i = 0; i < tasks_count; i++) {
        Task *task = tasks[i];
        pthread_mutex_destroy(&task->mutex);
    }

    threadpool_destroy(pool);
    pool = NULL;

    return 0;
}
